// Copyright (c) 2023 CHANGLEI. All rights reserved.

import 'package:arith/src/arith.dart' as arith;
import 'package:arith/src/describable.dart';

/// Created by changlei on 2023/6/14.
///
/// 构建公式
final class MathParser implements Describable {
  /// 构建公式
  MathParser(this.expression);

  /// 公式
  final String expression;

  final _callables = <arith.Callable>{};
  final _variables = <String, arith.ValueGetter<num>>{};

  /// 自定义函数
  Set<arith.Callable> get callables => Set.unmodifiable(_callables);

  set callables(Set<arith.Callable> callables) {
    _callables.addAll(callables);
  }

  /// 变量
  Map<String, arith.ValueGetter<num>> get variables => Map.unmodifiable(_variables);

  set variables(Map<String, arith.ValueGetter<num>> variables) {
    _variables.addAll(variables);
  }

  /// 添加自定义函数
  MathParser callable(String symbol, num Function(List<num> values) call) {
    _callables.add(arith.Callable(symbol, call));
    return this;
  }

  /// 添加变量
  MathParser variable(String name, arith.ValueGetter<num> value) {
    _variables[name] = value;
    return this;
  }

  /// 构建
  arith.Expression build() => arith.parse(expression, callables);

  /// 执行
  num evaluate() => build().call(variables);

  @override
  String toDescribe([bool isTight = false]) {
    final expression = build();
    return [
      expression.toDescribe(isTight, variables),
      '=',
      expression(variables),
    ].join(isTight ? '' : ' ');
  }

  @override
  String toString() => toDescribe();
}
